﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;

using ThresholdModeling;
using libUtilities;

namespace TTServer
{
    public partial class FormSetting : Form
    {
        private bool NewOrEdit = false; //true: new , false: edit
        private List<MemberInfo> members = new List<MemberInfo>();
        private bool isConstructSecret = false;
        private bool isFormLoad = true;
        private List<MembersGroup> _groups = new List<MembersGroup>(); //just have id and name
        private static int enterPasswordCount = 0;

        public List<MembersGroup> Groups
        {
            set { _groups = value; }
        }

        public FormSetting()
        {
            InitializeComponent();
        }

        private void FormSetting_Load(object sender, EventArgs e)
        {
            tbK.Text = "2";

            //String path = OtherUtils.getPath() + @"/Data/Group";
            //string[] files = TMUtils.GetFilesInDirectory(path);
            //if (files != null)
            //    cbGroup.DataSource = files;
            //if (files.Length != 0)
            //    FillGroupInfo(0);
            if (_groups.Count != 0)
            {
                List<String> groupsName = new List<string>();
                foreach (MembersGroup group in _groups)
                {
                    groupsName.Add("Group " + group.GroupName);
                }
                cbGroup.DataSource = groupsName;
            }

            gbEdit.Enabled = false;

            isFormLoad = false;
        }

        private void btNewGroup_Click(object sender, EventArgs e)
        {
            gbEdit.Enabled = true;
            gbEdit.Text = "New group Information";
            NewOrEdit = true;
            btDeleteGroup.Enabled = false;

            Reset();

            gvMemberList.Rows.Add();
            DataGridViewRow row = gvMemberList.Rows[0];
            row.Cells["gvcRole"].Value = "Key member";
            gvMemberList.Rows.Add();
            row = gvMemberList.Rows[1];
            row.Cells["gvcRole"].Value = "Member";

        }

        private void trbK_Scroll(object sender, EventArgs e)
        {
            tbK.Text = (trbK.Value + 2).ToString();
        }

        private void FillGroupInfo(int groupID)
        {
            List<MemberInfo> members = TMUtils.LoadGroup(groupID);
            if (members == null || members.Count == 0)
                return;
            MembersGroup group = members[0].Group;

            //Fill
            tbGroupName.Text = group.GroupName;
            tbPassword.Text = group.Password;
            tbK.Text = group.KMembers.ToString();
            trbK.Value = group.KMembers - 1;

            gvMemberList.Rows.Clear();
            gvMemberList.Rows.Add(members.Count);
            int i = 0;
            foreach (MemberInfo mem in members)
            {
                DataGridViewRow row = gvMemberList.Rows[i++];
                row.Cells["gvcID"].Value = mem.MemberID;
                row.Cells["gvcName"].Value = mem.Name;
                row.Cells["gvcEmail"].Value = mem.Email;
                row.Cells["gvcRole"].Value = mem.Role;
            }
        }

        private void btReset_Click(object sender, EventArgs e)
        {
            Reset();
        }

        private bool CheckValid()
        {
            String groupName = "".Equals(tbGroupName.Text) ? "No Name" : tbGroupName.Text;
            String pass = tbPassword.Text;
            String repass = tbRePassword.Text;
            if (!pass.Equals(repass))
            {
                MessageBox.Show("Two passwords MUST be the same!", "Error");
                return false;
            }

            int k = int.Parse(tbK.Text);
            int n = gvMemberList.Rows.Count - 1;
            if (n <= k)
            {
                MessageBox.Show("Minimum Accessible Members must be less than the numbers of members!", "Input Error");
                return false;
            }

            //String curDir = OtherUtils.getPath() + @"\Data\Group";
            //bool dirExist = Directory.Exists(curDir);
            //if (!dirExist)
            //{
            //    Directory.CreateDirectory(curDir);
            //}
            //string[] files = TMUtils.GetFilesPathInDirectory(curDir);
            //int nFiles = files.Length;
            int groupID = -1;
            if (!NewOrEdit)
            {
                groupID = _groups[cbGroup.SelectedIndex].GroupID;
                //int idx = cbGroup.SelectedIndex;
                //File.Delete(files[idx]);
                //groupID = idx;
            }
            //else
            //    groupID = nFiles + 1;
            MembersGroup group = new MembersGroup(groupID, groupName, pass, n, k);
            members.Clear();
            //List<MemberInfo> members = new List<MemberInfo>();
            for (int i = 0; i < n; i++)
            {
                DataGridViewRow row = gvMemberList.Rows[i];
                String memID = (String)row.Cells["gvcID"].Value;
                String name = (String)row.Cells["gvcName"].Value;
                String email = (String)row.Cells["gvcEmail"].Value;
                String role = (String)row.Cells["gvcRole"].Value;

                MemberInfo mem = new MemberInfo(memID, name, email, role, group);
                if (!mem.CheckValidInfo())
                {
                    MessageBox.Show("The information of the " + (i + 1).ToString() + " member is not valid.\n Please re-enter!", "Input error");
                    return false;
                }
                members.Add(mem);
            }

            bool validRule = CheckValidMembersRule(members);
            if (!validRule)
            {
                members.Clear();
                MessageBox.Show("Members information is not ALL correct.\n Please read the hint below!", "Input error");
                return false;
            }
            //btConstructSecret.Enabled = true;
            //btApply.Enabled = true;
            //MessageBox.Show("Valid input!", "Notify");
            return true;
        }

        private void btConstructSecret_Click(object sender, EventArgs e)
        {
            if (!CheckValid())
            {
                MessageBox.Show("Construct secret fail!", "Error");
                return;
            }
            MembersGroup group = members[0].Group;
            
            k_n_ThresholdModel tm = new k_n_ThresholdModel(group.NMembers, group.KMembers);
            //tm.ConstructThresholdPattern();
            bool suc = tm.ConstructSecret(members);
            if (suc)
            {
                isConstructSecret = true;
                MessageBox.Show("Construct secret successfully!", "Notify");
            }
            else
                MessageBox.Show("Construct secret unsuccessfully. Try again later!", "Error");
        }

        private void btApply_Click(object sender, EventArgs e)
        {
            if (!isConstructSecret && !CheckValid())
            {
                return;
            }
            //Init exponent cryptography
            int kExp, pExp;
            kExp = pExp = 0;
            bool initSuc = Cryptography.ExponentMod_Init(ref kExp, ref pExp);
            if (!initSuc)
            {
                MessageBox.Show("Initialize cryptography key is NOT successful.\n Please resconstruct again!", "Error Init");
                return;
            }
            foreach (MemberInfo mem in members)
            {
                mem.Group.K_ExpMod = kExp;
                mem.Group.P_ExpMod = pExp;
            }
            //Save SQL
            String editType = NewOrEdit ? "insert" : "update";
            bool suc = TMUtils.SaveGroup(members, editType);
            if (suc)
            {
                if (isConstructSecret)
                {
                    //Send email
                    bool sendMail = TMUtils.SendMail(members, Global.SystemEmailAddress, Global.SystemEmailPassword);
                    if (sendMail)
                    {
                        isConstructSecret = false;
                        MessageBox.Show("Save new group successfully! Emails are sent to each member", "Notify");
                        Reset();
                    }
                    else
                    {
                        MessageBox.Show("Emails are NOT sent to each member", "Error");
                    }
                }
            }
            else
                MessageBox.Show("Save new group fail! Try again", "Notify");

        }

        private bool CheckValidMembersRule(List<MemberInfo> mems)
        {
            //Valid admin
            bool validAdmin = true;
            int nAdmin = 0;
            foreach (MemberInfo memInfo in mems)
            {
                String role = memInfo.Role;
                if ("Key member".Equals(role) || "key member".Equals(role))
                    nAdmin++;
            }
            if (nAdmin != 1)
                validAdmin = false;

            return validAdmin;
        }

        private void cbGroup_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!isFormLoad)
            {
                int id = _groups[cbGroup.SelectedIndex].GroupID;
                MembersGroup group = TMUtils.LoadGroupInfo(id);
                String pass = "";
                bool isPressOK = false;
                int isCorrectPass = 0;
                do
                {
                    FormAskAdminPassword formAAP = new FormAskAdminPassword();
                    formAAP.ShowDialog();
                    pass = formAAP.ConfirmPassword;
                    isPressOK = formAAP.IsPressOK;
                    if (group.Password.Equals(pass) && isPressOK)
                        isCorrectPass = 1;
                    if (!isPressOK)
                        isCorrectPass = 2;
                    if (enterPasswordCount == 3)
                        isCorrectPass = 3;
                }
                while (isCorrectPass == 0);

                if (isCorrectPass == 1)
                {
                    gbEdit.Text = "Edit Group";
                    gbEdit.Enabled = true;
                    //btApply.Enabled = false;
                    btDeleteGroup.Enabled = true;
                    NewOrEdit = false;
                    FillGroupInfo(id);
                }

                if (isCorrectPass == 3)
                {
                    isCorrectPass = 0;
                    MessageBox.Show("You do NOT have permission to edit this group!", "Warning");
                    this.Close();
                }
            }
        }

        private void Reset()
        {
            tbGroupName.Clear();
            tbPassword.Clear();
            tbRePassword.Clear();
            trbK.Value = 0;
            tbK.Text = "2";
            gvMemberList.Rows.Clear();
        }

        private void btCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btDeleteGroup_Click(object sender, EventArgs e)
        {
            DialogResult res = MessageBox.Show("Are you sure to delete this group?", "Confirm deletion", MessageBoxButtons.YesNo);
            if (res == DialogResult.Yes)
            {
                //Delete this group
                bool suc = TMUtils.DeleteGroup(_groups[cbGroup.SelectedIndex].GroupID);
                if (suc)
                    MessageBox.Show("Delete successfully!", "Notify");
                else
                    MessageBox.Show("Delete fail!", "Error");
            }
        }

        private void btRefresh_Click(object sender, EventArgs e)
        {
            gbEdit.Enabled = false;
            _groups.Clear();
            _groups = TMUtils.LoadGroupsName();
            //cbGroup.Refresh();
            List<String> groupsName = new List<string>();
            if (_groups.Count != 0)
            {
                foreach (MembersGroup group in _groups)
                {
                    groupsName.Add("Group " + group.GroupName);
                }

            }
            isFormLoad = true;
            cbGroup.DataSource = groupsName;
            isFormLoad = false;
            cbGroup.Text = "";
            Reset();
        }
    }
}
